#pragma once

#include <map>
#include <vector>

#include "datetime/Timestamp.h"
#include "noncopyable.h"

#include "EventLoop.h"

struct pollfd; // 注意`Poller.h`并没有`include<poll.h>`，而是自己前向声明了`struct pollfd`，这不妨碍我们定义`vector<struct pollfd>`成员。

namespace learnmuduo
{
class Channel;

///
/// IO Multiplexing with poll(2).
///
/// This class doesn't own the Channel objects.
class Poller : noncopyable {
public:
  typedef std::vector<Channel*> ChannelList;

  Poller(EventLoop *loop);
  ~Poller();

  /// Polls the I/O events.
  /// Must be called in the loop thread.
  muduo::Timestamp poll(int timeoutMs, ChannelList *activeChannels); // 核心poll方法，返回发生事件的时间戳

  /// Changes the interested I/O events.
  /// Must be called in the loop thread.
  void updateChannel(Channel *channel); // 更新或注册Channel的关注事件

  void assertInLoopThread() { ownerLoop_->assertInLoopThread(); }

private:
  void fillActiveChannels(int numEvents, ChannelList *activeChannels) const; // 将poll结果填充到活跃Channel列表

  typedef std::vector<struct pollfd> PollFdList; // 缓存pollfd数组以减少开销: `Poller::poll()`不会在每次调用`poll(2)`之前临时构造`pollfd`数组，而是把它缓存起来（`pollfds_`）
  typedef std::map<int, Channel*> ChannelMap; // `ChannelMap`是从`fd`到`Channel*`的映射

  EventLoop *ownerLoop_; // `Poller`是`EventLoop`的间接成员，只供其owner `EventLoop`在IO线程调用，因此无须加锁。
  PollFdList pollfds_; // 当前注册的pollfd数组
  ChannelMap channels_; // 注册fd与Channel的关联表: `Poller`并不拥有`Channel`，`Channel`在析构之前必须自己unregister（`EventLoop::removeChannel()`），避免空悬指针。
};
} // namespace learnmuduo
